﻿using Aliyun.Acs.Core;
using Aliyun.Acs.Core.Exceptions;
using Aliyun.Acs.Core.Http;
using Aliyun.Acs.Core.Profile;
using Newtonsoft.Json;
using PMS.Core.Configuration.CommonEnumConfigs;
using PMS.Core.Utils;
using PMS.Data.Entities.Messages;
using PMS.Services.EntityServices.Logging;
using System.Collections.Generic;
using System.Linq;

namespace PMS.Services.Utils.Messages
{
    /// <summary>
    /// For AliDayu SDK detail: https://github.com/aliyun/aliyun-openapi-net-sdk/tree/master/aliyun-net-sdk-core
    /// </summary>
    public partial class AliyunSMSSender : ISMSSender
    {
        #region Fields
        private const string ApiEndpoint = "dysmsapi.aliyuncs.com";
        private const string ApiVersion = "2017-05-25";
        private const string DefaultRegion = "cn_hangzhou";
        private const int MAX_NUMS_PER_SEND = 1000;

        private readonly ILogger _logger;
        #endregion

        #region Ctor
        public AliyunSMSSender(ILogger logger)
        {
            _logger = logger;
        }
        #endregion

        #region Utils
        /// <summary>
        /// 将字典类型序列化为json字符串
        /// </summary>
        /// <typeparam name="TKey">字典key</typeparam>
        /// <typeparam name="TValue">字典value</typeparam>
        /// <param name="dict">要序列化的字典数据</param>
        /// <returns>json字符串</returns>
        public static string SerializeDictionaryToJsonString<TKey, TValue>(Dictionary<TKey, TValue> dict)
        {
            if (dict.Count == 0)
                return "";

            string jsonStr = JsonConvert.SerializeObject(dict);
            return jsonStr;
        }
        #endregion

        #region Methods

        /// <summary>
        /// 目前只支持阿里大鱼短信发送，查看了腾讯云短信发送接口，功能差不多
        /// 实际根据业务需要后期可增加不同短信提供商实现
        /// </summary>
        /// <param name="smsAccount"></param>
        /// <param name="phoneNumbers">
        /// 目前只提供了阿里大鱼短信SDK调用：
        /// 如为阿里短信SDK调用：
        /// SendSms接口是短信发送接口，支持在一次请求中向多个不同的手机号码发送同样内容的短信。
        /// phoneNumbers为多个手机号码,支持对多个手机号码发送短信，手机号码之间以英文逗号（,）分隔。上限为1000个手机号码。批量调用相对于单条调用及时性稍有延迟。
        /// </param>
        /// <param name="templateId"></param>
        /// <param name="templateParms"></param>
        /// <param name="msg"></param>
        /// <param name="extend"></param>
        /// <param name="ext"></param>
        /// <param name="nationCode"></param>
        /// <returns></returns>
        public bool SendSMS(SMSAccount smsAccount,
            string phoneNumbers,
            string templateId, Dictionary<string, string> templateParms,
            string msg = "", string extend = "",
            string ext = "", string nationCode = "+86")
        {
            if (smsAccount == null || !smsAccount.IsActive
                || string.IsNullOrEmpty(smsAccount.AccessKeyId)
                || string.IsNullOrEmpty(smsAccount.AccessKeySecret))
                throw new PMSException("AliDayu ShortMessageService_Not_Available_For_the_Moment", SystemLogLevel.Error);

            if (string.IsNullOrEmpty(phoneNumbers))
                throw new PMSException("Empty PhoneNumbers", SystemLogLevel.Error);

            if (string.IsNullOrEmpty(smsAccount.RegionID))
                smsAccount.RegionID = DefaultRegion;

            List<string> mobilePhones = new List<string>();
            phoneNumbers.Split(',').ToList().ForEach((phone) =>
            {
                mobilePhones.Add(nationCode + phone);
            });
            if (mobilePhones.Count > MAX_NUMS_PER_SEND)
                throw new PMSException("Ali SMS send limitation", SystemLogLevel.Error);
            
            phoneNumbers = string.Join(',', mobilePhones);
            IClientProfile profile = DefaultProfile.GetProfile(smsAccount.RegionID, smsAccount.AccessKeyId, smsAccount.AccessKeySecret);
            DefaultAcsClient client = new DefaultAcsClient(profile);
            CommonRequest request = new CommonRequest
            {
                Method = MethodType.POST,
                Domain = ApiEndpoint,
                Version = ApiVersion,
                Action = "SendSms"
            };
            // request.Protocol = ProtocolType.HTTP;
            request.AddQueryParameters("PhoneNumbers", phoneNumbers);
            request.AddQueryParameters("SignName", smsAccount.SignName);
            request.AddQueryParameters("TemplateCode", templateId);
            request.AddQueryParameters("TemplateParam", SerializeDictionaryToJsonString(templateParms));
            try
            {
                CommonResponse response = client.GetCommonResponse(request);
                //Console.WriteLine(System.Text.Encoding.Default.GetString(response.HttpResponse.Content));
                return response.HttpResponse.isSuccess();
            }
            catch (ServerException e)
            {
                //Console.WriteLine(e);
                //throw new PMSException("AliDayu ServerException", e);
                _logger.Error("AliDayu SMS ServerException", e, null);
                return false;
            }
            catch (ClientException e)
            {
                //Console.WriteLine(e);
                //throw new PMSException("AliDayu ClientException", e);
                _logger.Error("AliDayu SMS ClientException", e, null);
                return false;
            }
        }
        #endregion
    }
}
